package com.vdf.sisconsolid.persistencemodule.dao;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

import com.vdf.sisconsolid.persistencemodule.converter.ConsolidationConverter;
import com.vdf.sisconsolid.persistencemodule.dto.ConsolidationDTO;
import com.vdf.sisconsolid.persistencemodule.model.Address;
import com.vdf.sisconsolid.persistencemodule.model.Consolidation;
import com.vdf.sisconsolid.persistencemodule.model.Person;
import com.vdf.sisconsolid.persistencemodule.util.ConsolidationState;

public class ConsolidationDao extends BaseDao {
	
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	
	public void persist(Consolidation consolidation) {
		initTransaction();
		try {
			getEm().persist(consolidation.getPerson().getAddress());
			getEm().persist(consolidation.getPerson());
			getEm().persist(consolidation);
			commitTransaction();
		} catch (Throwable e) {
			e.printStackTrace();
			rollbackTransaction();
		}
	}

	public void remove(Long idConsolidation) {
		super.remove(Consolidation.class, idConsolidation);

	}
	
	public void cancel(Long idConsolidation) {
		initTransaction();
		try {
			Consolidation consolidation = getEm().find(Consolidation.class, idConsolidation);
			consolidation.setState(ConsolidationState.CANCELED.getCode());
			getEm().merge(consolidation);
			commitTransaction();
		} catch (Throwable e) {
			e.printStackTrace();
			rollbackTransaction();			
		}
	}

	public Consolidation merge(ConsolidationDTO cDTO) {
		Consolidation consolidation = ConsolidationConverter.toEntity(cDTO);
		initTransaction();
		try {
			Person person = consolidation.getPerson();
			Address address = getEm().merge(person.getAddress());
			person.setAddress(address);
			person = getEm().merge(person);
			consolidation.setPerson(person);
			consolidation = getEm().merge(consolidation);
			commitTransaction();
		} catch (Throwable e) {
			e.printStackTrace();
			rollbackTransaction();
		}
		return consolidation;
	}

	public ConsolidationDTO find(Long idConsolidation) {
		initTransaction();
		ConsolidationDTO consolidation = ConsolidationConverter
				.toDTO((Consolidation) getEm().find(Consolidation.class,
						idConsolidation));
		commitTransaction();
		return consolidation;
	}

	public List<ConsolidationDTO> getConsolidationList(
			Map<String, Object> parameters) {

		StringBuilder query = new StringBuilder(
				"SELECT cons FROM Consolidation cons where cons.state <> "
						+ ConsolidationState.CANCELED.getCode());

		if (parameters.size() > 0) {
			if (parameters.get("fromDate") != null) {
				query.append(" and cons.date >= :fromDate ");
				try {
					parameters.put("fromDate", dateFormat.parse((String) parameters.get("fromDate")));
				} catch (ParseException e) {
					parameters.remove("fromDate");
				}
			}
			if (parameters.get("toDate") != null) {
				query.append(" and cons.date <= :toDate ");
				try {
					parameters.put("toDate", dateFormat.parse((String) parameters.get("toDate")));
				} catch (ParseException e) {
					parameters.remove("toDate");
				}
			}
			if (parameters.get("family") != null) {
				query.append(" and cons.cell.family.id = :family ");
				parameters.put("family", ((Integer)parameters.get("family")).longValue());
			}
			if (parameters.get("firstName") != null) {
				query.append(" and cons.person.firstName = :firstName ");
			}
			if (parameters.get("lastName") != null) {
				query.append(" and cons.person.lastName = :lastName ");
			}
			if (parameters.get("assignedTo") != null) {
				query.append(" and cons.assignedTo.id = :assignedTo ");
				parameters.put("assignedTo", ((Integer)parameters.get("assignedTo")).longValue());
			}
			if (parameters.get("tookData") != null) {
				query.append(" and cons.tookData.id = :tookData ");
				parameters.put("tookData", ((Integer)parameters.get("tookData")).longValue());
			}
			if (parameters.get("attendedCell") != null) {
				boolean attended = (Boolean) parameters.get("attendedCell");
				query.append(" and (SELECT COUNT(t.id) FROM cons.tracings t WHERE t.attendedCell = 1 )" + (attended ? ">" : "=") + "0");
				parameters.remove("attendedCell");
			}
		}
		super.initTransaction();
		List<ConsolidationDTO> cDTOList = ConsolidationConverter
				.toDTOList((List<Consolidation>) super
						.listAllWithoutTransaction(query.toString(), parameters));
		super.commitTransaction();
		return cDTOList;
	}
}
